using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using DevExpress.XtraEditors;
using twistmachinev2.CommonUse;
using twistmachinev2.OPCUA;
using System.Reflection;
using twistmachinev2.Entity;

namespace twistmachinev2
{
    public partial class FrmRunForm : BaseOpcUaForm
    {
        private DynamicOpcUaMapper dynamicMapper;
        private int logCount = 0;
        private const int MAX_LOG_COUNT = 50;

        public FrmRunForm()
        {
            InitializeComponent();
            BindingModel();
            InitializeLogDisplay();
        }

        /// <summary>
        /// 初始化日志显示
        /// </summary>
        private void InitializeLogDisplay()
        {
            // 设置RichTextBox的现代化样式
            richTextBox1.BackColor = Color.FromArgb(248, 249, 250);
            richTextBox1.ForeColor = Color.FromArgb(64, 64, 64);
            richTextBox1.Font = new Font("Consolas", 10F, FontStyle.Regular);
            richTextBox1.ReadOnly = true;
            richTextBox1.ScrollBars = RichTextBoxScrollBars.Vertical;

            // 添加欢迎信息
            AddLogMessage("系统启动", "运行画面已加载，准备就绪", LogLevel.Info);
        }

        /// <summary>
        /// 日志级别枚举
        /// </summary>
        public enum LogLevel
        {
            Info,
            Success,
            Warning,
            Error
        }

        /// <summary>
        /// 添加日志消息到RichTextBox
        /// </summary>
        /// <param name="category">日志分类</param>
        /// <param name="message">日志消息</param>
        /// <param name="level">日志级别</param>
        private void AddLogMessage(string category, string message, LogLevel level)
        {
            if (richTextBox1.InvokeRequired)
            {
                richTextBox1.Invoke(new Action(() => AddLogMessage(category, message, level)));
                return;
            }

            try
            {
                // 检查日志数量，超过限制则清空
                if (logCount >= MAX_LOG_COUNT)
                {
                    richTextBox1.Clear();
                    logCount = 0;

                    // 添加清空提示
                    var clearTime = DateTime.Now.ToString("HH:mm:ss");
                    richTextBox1.SelectionColor = Color.FromArgb(108, 117, 125);
                    richTextBox1.SelectionFont = new Font("Consolas", 9F, FontStyle.Italic);
                    richTextBox1.AppendText($"[{clearTime}] ═══════════════════════════════════════\n");
                    richTextBox1.AppendText($"[{clearTime}] 📋 日志已自动清空 (超过{MAX_LOG_COUNT}条记录)\n");
                    richTextBox1.AppendText($"[{clearTime}] ═══════════════════════════════════════\n\n");
                    logCount += 3;
                }

                // 获取当前时间
                var timestamp = DateTime.Now.ToString("HH:mm:ss.fff");

                // 根据日志级别设置颜色和图标
                Color levelColor;
                string levelIcon;
                FontStyle fontStyle = FontStyle.Regular;

                switch (level)
                {
                    case LogLevel.Success:
                        levelColor = Color.FromArgb(40, 167, 69);
                        levelIcon = "✅";
                        break;
                    case LogLevel.Warning:
                        levelColor = Color.FromArgb(255, 193, 7);
                        levelIcon = "⚠️";
                        fontStyle = FontStyle.Bold;
                        break;
                    case LogLevel.Error:
                        levelColor = Color.FromArgb(220, 53, 69);
                        levelIcon = "❌";
                        fontStyle = FontStyle.Bold;
                        break;
                    case LogLevel.Info:
                    default:
                        levelColor = Color.FromArgb(23, 162, 184);
                        levelIcon = "ℹ️";
                        break;
                }

                // 添加时间戳
                richTextBox1.SelectionColor = Color.FromArgb(108, 117, 125);
                richTextBox1.SelectionFont = new Font("Consolas", 9F, FontStyle.Regular);
                richTextBox1.AppendText($"[{timestamp}] ");

                // 添加图标和分类
                richTextBox1.SelectionColor = levelColor;
                richTextBox1.SelectionFont = new Font("Consolas", 10F, fontStyle);
                richTextBox1.AppendText($"{levelIcon} [{category}] ");

                // 添加消息内容
                richTextBox1.SelectionColor = Color.FromArgb(64, 64, 64);
                richTextBox1.SelectionFont = new Font("Consolas", 10F, FontStyle.Regular);
                richTextBox1.AppendText($"{message}\n");

                // 自动滚动到底部
                richTextBox1.SelectionStart = richTextBox1.Text.Length;
                richTextBox1.ScrollToCaret();

                logCount++;
            }
            catch (Exception ex)
            {
                // 避免日志记录本身出错导致的无限循环
                System.Diagnostics.Debug.WriteLine($"日志记录失败: {ex.Message}");
            }
        }

        private void BindingModel()
        {
            var dataModel = GetDataModel("TwistMachine");

            // 遍历所有控件，为DataBindingStatusCircle类型的控件设置DataModel
            SetDataModelForControls(this, dataModel);
        }

        /// <summary>
        /// 递归遍历控件及其子控件，为DataBindingStatusCircle类型的控件设置DataModel
        /// </summary>
        /// <param name="parent">父控件</param>
        /// <param name="dataModel">数据模型</param>
        private void SetDataModelForControls(Control parent, DynamicDataModel dataModel)
        {
            foreach (Control control in parent.Controls)
            {
                // 检查控件类型是否为DataBindingStatusCircle
                if (control is TwistControl.DataBindingStatusCircle statusCircle)
                {
                    statusCircle.DataModel = dataModel;
                }
                // 检查控件类型是否为DataBindingTextBox
                else if (control is TwistControl.DataBindingTextBox textBox)
                {
                    textBox.DataModel = dataModel;
                }

                // 递归处理子控件
                if (control.HasChildren)
                {
                    SetDataModelForControls(control, dataModel);
                }
            }
        }

        private void panelControl1_Paint(object sender, PaintEventArgs e)
        {

        }
        /// <summary>
        /// 获取DynamicMapper实例
        /// </summary>
        /// <returns></returns>
        private DynamicOpcUaMapper GetDynamicMapper()
        {
            if (dynamicMapper == null)
            {
                var serviceManager = OpcUaServiceManager.Instance;
                // 通过反射获取私有字段_dynamicMapper
                var field = serviceManager.GetType().GetField("_dynamicMapper",
                    BindingFlags.NonPublic | BindingFlags.Instance);
                dynamicMapper = field?.GetValue(serviceManager) as DynamicOpcUaMapper;
            }
            return dynamicMapper;
        }

        /// <summary>
        /// 获取窗体上所有DataBindingTextBox控件
        /// </summary>
        /// <returns></returns>
        private List<TwistControl.DataBindingTextBox> GetAllDataBindingTextBoxes()
        {
            var textBoxes = new List<TwistControl.DataBindingTextBox>();
            GetDataBindingTextBoxesRecursive(this, textBoxes);
            return textBoxes;
        }

        /// <summary>
        /// 递归获取所有DataBindingTextBox控件
        /// </summary>
        /// <param name="parent">父控件</param>
        /// <param name="textBoxes">结果列表</param>
        private void GetDataBindingTextBoxesRecursive(Control parent, List<TwistControl.DataBindingTextBox> textBoxes)
        {
            foreach (Control control in parent.Controls)
            {
                if (control is TwistControl.DataBindingTextBox textBox)
                {
                    //修改了ReadOnly属性的判断逻辑
                    if (textBox.ReadOnly == false)
                        textBoxes.Add(textBox);
                }

                // 递归处理子控件
                if (control.HasChildren)
                {
                    GetDataBindingTextBoxesRecursive(control, textBoxes);
                }
            }
        }

        /// <summary>
        /// 下发到PLC中
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void btnSend_Click(object sender, EventArgs e)
        {
            try
            {
                // 更新状态
                toolStripStatusLabel1.Text = "正在下发数据到PLC...";
                btnSend.Enabled = false;

                AddLogMessage("数据下发", "开始下发数据到PLC...", LogLevel.Info);

                var mapper = GetDynamicMapper();
                if (mapper == null)
                {
                    var errorMsg = "无法获取OPC UA映射器，请检查连接状态";
                    AddLogMessage("连接错误", errorMsg, LogLevel.Error);
                    MessageBox.Show(errorMsg, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                // 获取所有DataBindingTextBox控件
                var textBoxes = GetAllDataBindingTextBoxes();
                if (textBoxes.Count == 0)
                {
                    var infoMsg = "未找到任何数据绑定文本框";
                    AddLogMessage("数据检查", infoMsg, LogLevel.Warning);
                    MessageBox.Show(infoMsg, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return;
                }

                AddLogMessage("数据检查", $"找到 {textBoxes.Count} 个数据绑定控件", LogLevel.Info);

                // 准备要写入的数据
                var writeOperations = new List<(string nodeId, object value, string controlName)>();

                foreach (var textBox in textBoxes)
                {
                    // 检查是否有绑定的属性名称
                    if (!string.IsNullOrEmpty(textBox.PropertyName))
                    {
                        // 获取对应的节点配置信息
                        var nodeConfig = GetNodeConfigByPropertyName(textBox.PropertyName);
                        if (nodeConfig != null)
                        {
                            // 检查节点是否可写
                            if (nodeConfig.AccessLevel.Contains("Write"))
                            {
                                // 获取当前文本框的值并根据节点数据类型进行转换
                                var textValue = textBox.Text;
                                object value = ConvertValueByDataType(textValue, nodeConfig.DataType);

                                writeOperations.Add((nodeConfig.NodeId, value, textBox.Name));
                            }
                            else
                            {
                                AddLogMessage("权限检查", $"节点 '{nodeConfig.NodeId}' (属性: {textBox.PropertyName}) 不可写，跳过写入操作", LogLevel.Warning);
                            }
                        }
                    }
                }

                if (writeOperations.Count == 0)
                {
                    var noDataMsg = "没有找到可写入的数据";
                    AddLogMessage("数据验证", noDataMsg, LogLevel.Warning);
                    MessageBox.Show(noDataMsg, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return;
                }

                AddLogMessage("数据准备", $"准备写入 {writeOperations.Count} 个节点", LogLevel.Info);

                // 执行批量写入操作
                int successCount = 0;
                int failCount = 0;
                var errorMessages = new List<string>();

                foreach (var (nodeId, value, controlName) in writeOperations)
                {
                    try
                    {
                        var result = await mapper.WriteNodeAsync(nodeId, value);
                        if (result.IsSuccess)
                        {
                            successCount++;
                            AddLogMessage("写入成功", $"节点 {nodeId} = {value} (控件: {controlName})", LogLevel.Success);
                        }
                        else
                        {
                            failCount++;
                            var errorMsg = $"控件 {controlName} -> 节点 {nodeId}：{result.Message}";
                            errorMessages.Add(errorMsg);
                            AddLogMessage("写入失败", errorMsg, LogLevel.Error);
                        }
                    }
                    catch (Exception ex)
                    {
                        failCount++;
                        var errorMsg = $"控件 {controlName} -> 节点 {nodeId}：{ex.Message}";
                        errorMessages.Add(errorMsg);
                        AddLogMessage("写入异常", errorMsg, LogLevel.Error);
                    }
                }

                // 显示结果
                var resultMessage = $"数据下发完成！\n成功：{successCount} 项\n失败：{failCount} 项";
                if (errorMessages.Count > 0)
                {
                    resultMessage += $"\n\n失败详情：\n{string.Join("\n", errorMessages.Take(5))}";
                    if (errorMessages.Count > 5)
                    {
                        resultMessage += $"\n... 还有 {errorMessages.Count - 5} 项失败";
                    }
                }

                var icon = failCount == 0 ? MessageBoxIcon.Information : MessageBoxIcon.Warning;
                MessageBox.Show(resultMessage, "下发结果", MessageBoxButtons.OK, icon);

                // 添加汇总日志
                if (failCount == 0)
                {
                    AddLogMessage("下发完成", $"全部成功！共处理 {successCount} 个节点", LogLevel.Success);
                }
                else
                {
                    AddLogMessage("下发完成", $"成功: {successCount} 个，失败: {failCount} 个", LogLevel.Warning);
                }

                toolStripStatusLabel1.Text = $"下发完成 - 成功：{successCount}，失败：{failCount}";
            }
            catch (Exception ex)
            {
                var exceptionMsg = $"下发数据时发生异常：{ex.Message}";
                AddLogMessage("系统异常", exceptionMsg, LogLevel.Error);
                MessageBox.Show(exceptionMsg, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                toolStripStatusLabel1.Text = "下发失败";
            }
            finally
            {
                btnSend.Enabled = true;
            }
        }

        /// <summary>
        /// 根据属性名称获取对应的OPC UA节点配置
        /// </summary>
        /// <param name="propertyName">属性名称</param>
        /// <returns>节点配置</returns>
        private OpcUaNodeConfigEntity GetNodeConfigByPropertyName(string propertyName)
        {
            try
            {
                // 从OPC UA配置服务中获取节点配置
                var configService = OpcUaServiceManager.Instance.ConfigService;
                if (configService == null)
                {
                    AddLogMessage("配置错误", $"OPC UA配置服务未初始化，无法获取PropertyName '{propertyName}' 对应的节点配置", LogLevel.Warning);
                    return null;
                }

                // 获取所有节点配置
                var allNodes = configService.GetAllNodes();
                if (allNodes == null || allNodes.Count == 0)
                {
                    AddLogMessage("配置错误", "未找到任何OPC UA节点配置", LogLevel.Warning);
                    return null;
                }

                // 根据PropertyName查找对应的节点配置
                var nodeConfig = allNodes.FirstOrDefault(n => n.PropertyName == propertyName);
                if (nodeConfig == null)
                {
                    AddLogMessage("配置查找", $"未找到PropertyName '{propertyName}' 对应的节点配置", LogLevel.Warning);
                    return null;
                }

                return nodeConfig;
            }
            catch (Exception ex)
            {
                AddLogMessage("配置异常", $"获取PropertyName '{propertyName}' 对应的节点配置时发生异常：{ex.Message}", LogLevel.Error);
                return null;
            }
        }

        /// <summary>
        /// 根据属性名称获取对应的OPC UA节点ID（兼容性方法）
        /// </summary>
        /// <param name="propertyName">属性名称</param>
        /// <returns>节点ID</returns>
        private string GetNodeIdByPropertyName(string propertyName)
        {
            var nodeConfig = GetNodeConfigByPropertyName(propertyName);
            return nodeConfig?.NodeId;
        }

        /// <summary>
        /// 根据数据类型转换值
        /// </summary>
        /// <param name="textValue">文本值</param>
        /// <param name="dataType">数据类型</param>
        /// <returns>转换后的值</returns>
        private object ConvertValueByDataType(string textValue, string dataType)
        {
            if (string.IsNullOrEmpty(textValue))
                return null;

            try
            {
                switch (dataType?.ToUpper())
                {
                    case "BOOLEAN":
                    case "BOOL":
                        if (bool.TryParse(textValue, out bool boolValue))
                            return boolValue;
                        // 尝试将数字转换为布尔值（0=false, 非0=true）
                        if (int.TryParse(textValue, out int intForBool))
                            return intForBool != 0;
                        break;

                    case "INT16":
                    case "SHORT":
                        if (short.TryParse(textValue, out short shortValue))
                            return shortValue;
                        break;

                    case "INT32":
                    case "INT":
                    case "INTEGER":
                        if (int.TryParse(textValue, out int intValue))
                            return intValue;
                        break;

                    case "INT64":
                    case "LONG":
                        if (long.TryParse(textValue, out long longValue))
                            return longValue;
                        break;

                    case "UINT16":
                    case "USHORT":
                        if (ushort.TryParse(textValue, out ushort ushortValue))
                            return ushortValue;
                        break;

                    case "UINT32":
                    case "UINT":
                        if (uint.TryParse(textValue, out uint uintValue))
                            return uintValue;
                        break;

                    case "UINT64":
                    case "ULONG":
                        if (ulong.TryParse(textValue, out ulong ulongValue))
                            return ulongValue;
                        break;

                    case "FLOAT":
                    case "SINGLE":
                        if (float.TryParse(textValue, out float floatValue))
                            return floatValue;
                        break;

                    case "DOUBLE":
                        if (double.TryParse(textValue, out double doubleValue))
                            return doubleValue;
                        break;

                    case "DECIMAL":
                        if (decimal.TryParse(textValue, out decimal decimalValue))
                            return decimalValue;
                        break;

                    case "STRING":
                    case "TEXT":
                    default:
                        return textValue;
                }
            }
            catch (Exception ex)
            {
                AddLogMessage("数据转换", $"类型转换失败，数据类型: {dataType}, 值: {textValue}, 错误: {ex.Message}", LogLevel.Warning);
            }

            // 如果转换失败，返回原始字符串值
            AddLogMessage("数据转换", $"无法将值 '{textValue}' 转换为类型 '{dataType}'，将使用原始字符串值", LogLevel.Warning);
            return textValue;
        }
    }
}
